package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.enums.MediaEnum;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.dto.WmNewsDto;
import com.heima.media.dto.WmNewsPageDto;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmNewsMaterial;
import com.heima.media.mapper.WmNewsMapper;
import com.heima.media.service.IAuditService;
import com.heima.media.service.IWmMaterialService;
import com.heima.media.service.IWmNewsMaterialService;
import com.heima.media.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-03-25
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Autowired
    private IWmNewsMaterialService wmNewsMaterialService;


    @Autowired
    private IAuditService auditService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    /**
     * 文章上下架话题
     */
    @Value("${topic.upDownTopic}")
    private String upDownTopic;

    /**
     * 自媒体用户根据条件查询自媒体提审文章列表
     *
     * @param dto 查询条件
     * @return 分页自媒体提审文章列表
     */
    @Override
    public ResponseResult listByCondition(WmNewsPageDto dto) {
        User user = UserThreadLocalUtil.get();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //1.构建查询条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        //1.1 根据自媒体用户ID查询自己提审文章
        queryWrapper.eq(WmNews::getUserId, user.getUserId());
        //1.2 根据提审文章状态
        if (dto.getStatus() != null) {
            queryWrapper.eq(WmNews::getStatus, dto.getStatus());
        }
        //1.3 根据频道ID查询
        if (dto.getChannelId() != null) {
            queryWrapper.eq(WmNews::getChannelId, dto.getChannelId());
        }
        //1.4 根据自媒体文章标题模糊查询
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            queryWrapper.like(WmNews::getTitle, dto.getKeyword());
        }
        //1.5 根据发布时间区间查询
        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
            queryWrapper.between(WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate());
        }
        //1.6 根据创建时间排序
        queryWrapper.orderByDesc(WmNews::getCreatedTime);

        //2.构建分页对象
        IPage<WmNews> page = new Page<>(dto.getPage(), dto.getSize());

        //3.执行分页查询
        page = this.page(page, queryWrapper);

        //4.封装分页结果
        return new PageResponseResult(dto.getPage(), dto.getSize(), page.getTotal(), page.getRecords());
    }


    /**
     * 自媒体文章提交审核
     *
     * @param dto 文章信息
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult submit(WmNewsDto dto) {
        //1.获取登录用户
        User user = UserThreadLocalUtil.get();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //2.构建自媒体（提审）文章对象，被对象中属性进行复制  DTO---->PO，保存自媒体文章
        WmNews wmNews = new WmNews();
        //2.1 将提交DTO中属性值拷贝到PO对象中
        BeanUtils.copyProperties(dto, wmNews);
        wmNews.setUserId(user.getUserId());

        //2.2 设置文章的封面
        //2.2.0 从文章正文中获取图片
        List<ImageDto> contentImages = getImagesFromContent(dto.getContent());
        //2.2.1 判断用户选择封面类型：单图 三图 无图（不需要处理） 自动
        List<ImageDto> imageDtoList = dto.getImages();

        //2.2.2 处理封面单图或者三图 判断依据：images属性值
        if (!CollectionUtils.isEmpty(imageDtoList)) {
            //采用Stream流处理封面集合  List<ImageDTO>封面集合----->List<String>图片集合---->String图片字符串
            String images = imageDtoList.stream()
                    .map(ImageDto::getUrl)
                    .collect(Collectors.joining(","));
            wmNews.setImages(images);
        } else if (CollectionUtils.isEmpty(imageDtoList) && dto.getType() == -1) {
            //2.3.3 处理自动封面为自动  如果正文中图片数量大于3 截取前三张图片作为封面，将类型封面设置三图；正文图片数量小于三，截取第一张图片，封面类型单图；正文无图，设置无图，类型：无图
            if (CollectionUtils.isEmpty(contentImages)) {
                //正文中无图 将type封面类型设置为0
                wmNews.setType(0);
            } else if (contentImages.size() < 3) {
                //正文中图片小于3 截取第一张图片作为封面 设置封面类型为单图
                String images = contentImages.get(0).getUrl();
                wmNews.setImages(images);
                wmNews.setType(1);
            } else {
                //正文中图片大于3 截取前三张图片作为封面 设置封面类型为3图
                String images = contentImages.subList(0, 3).stream().map(ImageDto::getUrl).collect(Collectors.joining(",")); //截取集合中三个对象
                wmNews.setImages(images);
                wmNews.setType(3);
            }
        }
        //2.3 执行保存自媒体文章
        this.save(wmNews);

        //3.如果不是草稿状态，将文章中封面以及文章内容素材跟文章进行关联
        if (!dto.getStatus().equals(MediaEnum.NEWS_SUBMIT_STATUS_DRAFT.getVal())) {
            //如果用户操作不是保存草稿
            //3.1 设置文章跟 封面素材关系
            List<ImageDto> converImageList = dto.getImages();
            saveArticleMaterialRelation(converImageList, MediaEnum.MATERIAL_TYPE_REF_TYPE_CONVERIMG.getVal(), wmNews.getId());
            //3.2 设置文章 跟 正文中素材关系
            saveArticleMaterialRelation(contentImages, MediaEnum.MATERIAL_TYPE_REF_TYPE_CONTENTIMG.getVal(), wmNews.getId());
        }


        //TODO 进入自媒体文章审核业务方法----审核service中完成审核  实现audit方法
        auditService.audit(wmNews);

        return ResponseResult.okResult();
    }


    /**
     * 将文章跟素材建立关联
     *
     * @param imageDtoList 内容图片集合 或者 正文图片集合
     * @param type         0：内容引入  1：封面引用
     * @param newsId       文章ID
     */
    private void saveArticleMaterialRelation(List<ImageDto> imageDtoList, Integer type, Integer newsId) {
        int ord = 0;
        if (!CollectionUtils.isEmpty(imageDtoList)) {
            for (ImageDto imageDto : imageDtoList) {
                WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
                wmNewsMaterial.setMaterialId(imageDto.getId());
                wmNewsMaterial.setNewsId(newsId);
                wmNewsMaterial.setType(type);
                wmNewsMaterial.setOrd(ord++);
                wmNewsMaterialService.save(wmNewsMaterial);
            }
        }
    }


    /**
     * 从文章正文中获取图片
     *
     * @param content 文章正文
     *                content: "[{\"type\":\"text\",\"value\":\"第一段内容\\n\"},{\"type\":\"image\",\"value\":\"http://192.168.137.136:9000/leadnews/0edb5264-a033-4a47-a586-43a51b4ce73a.png\",\"id\":120}]
     * @return
     */
    private List<ImageDto> getImagesFromContent(String content) {
        //1.采用FastJSON转换  将字符串转为java对象 String---->ContentDTO
        List<ContentDto> contentDtos = JSON.parseArray(content, ContentDto.class);
        //2.遍历段落集合 获取图片
        if (!CollectionUtils.isEmpty(contentDtos)) {
            List<ImageDto> imageDtos = new ArrayList<>();
            for (ContentDto contentDto : contentDtos) {
                if ("image".equals(contentDto.getType())) {
                    ImageDto imageDto = new ImageDto();
                    imageDto.setId(contentDto.getId());
                    imageDto.setUrl(contentDto.getValue());
                    imageDtos.add(imageDto);
                }
            }
            return imageDtos;
        }
        return null;
    }


    /**
     * 将指定的自媒体文章进行上架|下架处理
     *
     * @param dto 自媒体文章ID  状态
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        //1.根据自媒体文章ID查询自媒体文章对象,根据状态判断是否允许上下架处理
        WmNews wmNews = this.getById(dto.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        Integer status = wmNews.getStatus();
        if (status != null && status.equals(MediaEnum.NEWS_SUBMIT_STATUS_PUBLISH)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_CAN_NOT_UPDATE);
        }

        //2.更新自媒体文章状态
        Integer enable = dto.getEnable();
        wmNews.setEnable(enable == 0 ? false : true);
        this.updateById(wmNews);

        //3.发送消息到Kafka中 异步 下架正式发布文章
        HashMap<String, Object> data = new HashMap<>();
        data.put("articleId", wmNews.getArticleId());
        data.put("isDown", enable == 1 ? false : true);
        //将数据转为JSON
        String message = JSON.toJSONString(data);
        kafkaTemplate.send(upDownTopic, message);
        return ResponseResult.okResult();
    }

}
